//
//  UIScrollView+PullRefresh.m
//  PhoneBookBag
//
//  Created by 吴海超 on 14/8/20.
//  Copyright (c) 2014年 吴海超. All rights reserved.
//

#import "UIScrollView+PullRefresh.h"
#import "UIView+LXExpanding.h"
#import <objc/runtime.h>

#define k_Margin              (5.0)                //上下边距
#define k_WaterDropSize       (30.0)               //水滴尺寸
#define k_PullHeight          (80.0)               //下拉高度
#define k_BreakRadius         (5.0)                //断开半径
#define k_OffsetAnimationTime (0.2)                //偏移动画时间
#define k_FontSize            (14.0)               //字体大小
#define k_ContentOffset       (@"contentOffset")   //监听路径
#define k_ContentInset        (@"contentInset")
#define k_ContentSize         (@"contentSize")
#define k_RefreshFinishTxt    (@"刷新完成")
#define k_LoadMoreTxt         (@"加载更多")
#define k_LoadingTxt          (@"正在加载")
#define k_RefreshingHeight    (k_WaterDropSize + 2.0 * k_Margin)    //刷新视图的高度

//加载器渐变开始颜色
#define K_StartColor      ([UIColor colorWithRed:255.0 / 255.0\
                                              green:255.0 / 255.0\
                                               blue:255.0 / 255.0\
                                               alpha:1.0].CGColor)
//加载器渐变结束颜色
#define K_EndColor        (kAppThemeColor.CGColor)
//水滴颜色
#define k_WaterBackColor  (kAppThemeColor.CGColor)

//刷新头部提示文字颜色
#define k_HeaderLableTxtColor  (kAppNormalTextColor)

//刷新头部百分比标签文字颜色
#define k_HeaderPercentLabTxtColor ([UIColor whiteColor])

//刷新底部提示文字颜色
#define k_FooterLableTxtColor  (kAppNormalTextColor)

//刷新底部百分比标签文字颜色
#define k_FooterPercentLabTxtColor ([UIColor grayColor])
typedef enum{
    NoneRefresh = 3,        //没有刷新
    WillRefresh,            //将要刷新
    DoingRefresh,           //正在刷新
    DidRefreshed            //完成刷新
}RefreshStatus;

#pragma mark - 上拉刷新视图 -

@interface PullFooterView : UIView
@property (nonatomic, assign) BOOL                    isSetOffset;                //是否已经设置了偏移
@property (nonatomic, assign) RefreshStatus        currentRefreshState;        //当前刷新状态
@property (nonatomic, assign) UIEdgeInsets            superOriginalContentInset;  //super原始偏移值
- (void)setProgressValue:(CGFloat)progressValue;
- (void)updatePostion;
@end

@interface PullFooterView (){
    UIView             *           _backView;                    //背景视图
    UILabel            *           _loadLab;                     //加载标签
    UILabel            *           _percentLab;                  //百分比标签
    UIImageView        *           _progressBarImageView;        //进度条
    CAGradientLayer    *           _gradientProgressBar;         //渐变进度条层
    CAShapeLayer       *           _progressBar;                 //进度条层
    id                             _delegate;                    //刷新代理
    UIScrollView       *           _superView;                   //父视图
    
    BOOL                           _isDidSendRequest;            //是否已经发生请求
}
@end

@implementation PullFooterView

- (instancetype)initWithFrame:(CGRect)frame delegate:(id<PullRefreshDelegate>)delegate{
    self = [super initWithFrame:frame];
    if(self){
        _delegate = delegate;
        [self initData];
    }
    return self;
}

- (void)willMoveToSuperview:(UIView *)newSuperview{
    [super willMoveToSuperview:newSuperview];
    [_superView cancelledObsever];
    if(newSuperview){
        [_superView addObserver];
    }
}

+ (CGFloat)stringWidth:(NSString *)content constrainedHeight:(CGFloat)height fontSize:(CGFloat)fontSize{
#pragma clang diagnostic push
#pragma clang diagnostic ignored"-Wdeprecated-declarations"
    CGSize contentSize = [content sizeWithFont:[UIFont systemFontOfSize:fontSize] constrainedToSize:CGSizeMake(MAXFLOAT, height)];
#pragma clang diagnostic pop
    return contentSize.width;
}

- (void)initData{
    _currentRefreshState = NoneRefresh;
    CGFloat loadingLabWidth = [PullFooterView stringWidth:k_LoadMoreTxt constrainedHeight:self.lx_height fontSize:17.0];
    CGFloat sumWidth = loadingLabWidth + k_WaterDropSize +k_Margin;
    _backView = [[UIView alloc]initWithFrame:CGRectMake((self.lx_width - sumWidth) / 2.0, k_Margin, k_WaterDropSize, k_WaterDropSize)];
    _loadLab = [[UILabel alloc]initWithFrame:CGRectMake(_backView.lx_maxX + k_Margin, 0, loadingLabWidth, self.lx_height)];
    _loadLab.text = k_LoadMoreTxt;
    _loadLab.textColor = k_FooterLableTxtColor;
    _loadLab.font = [UIFont systemFontOfSize:k_FontSize];
    [self addSubview:_loadLab];
    [self addSubview:_backView];
    
    _percentLab = [[UILabel alloc]initWithFrame:_backView.bounds];
    _percentLab.textAlignment = NSTextAlignmentCenter;
    _percentLab.font = [UIFont systemFontOfSize:10.0];
    _percentLab.textColor = k_FooterPercentLabTxtColor;
    _percentLab.text = @"0";
    _percentLab.hidden = YES;
    [_backView addSubview:_percentLab];
    
    _gradientProgressBar = [CAGradientLayer layer];
    _gradientProgressBar.frame = _backView.bounds;
    _gradientProgressBar.backgroundColor = [UIColor clearColor].CGColor;
    _gradientProgressBar.colors = @[(id)K_StartColor , (id)K_EndColor];
    _gradientProgressBar.locations = @[@(0.0) , @(1.0)];
    
    _progressBar = [CAShapeLayer layer];
    _progressBar.frame = _backView.bounds;
    _progressBar.backgroundColor = [UIColor clearColor].CGColor;
    _progressBar.fillColor = [UIColor clearColor].CGColor;
    _progressBar.strokeColor = [UIColor blueColor].CGColor;
    _progressBar.lineWidth = 5.0;
    _gradientProgressBar.mask = _progressBar;
    
    [_backView.layer addSublayer:_gradientProgressBar];
    
    _progressBarImageView = [[UIImageView alloc]initWithFrame:_backView.frame];
}

- (void)updateProgressBarWithValue:(CGFloat)value{
    value = value < 0 ? 0 : value;
    CGFloat endAngle = value / k_RefreshingHeight;
    if (endAngle > 1.0){
        endAngle = 1.0;
    }
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddArc(path, NULL, _progressBar.frame.size.width / 2.0, _progressBar.frame.size.height / 2.0, k_WaterDropSize / 2.0 - 3.0, -M_PI / 2.0, endAngle * M_PI * 2.0 - M_PI / 2.0, NO);
    _progressBar.path = path;
    _percentLab.text = [NSString stringWithFormat:@"%.0f",endAngle * 100.0];
    CGPathRelease(path);
}

- (UIImage *)getProgressBarImage{
    UIGraphicsBeginImageContext(_gradientProgressBar.frame.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    [_gradientProgressBar renderInContext:context];
    return UIGraphicsGetImageFromCurrentImageContext();
}

- (void)setImageProgressBarAnimation{
    CABasicAnimation *ba = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    ba.fromValue = @(0);
    ba.toValue = @(M_PI * 2.0);
    ba.duration = 1.0;
    ba.cumulative = YES;
    ba.repeatCount = INFINITY;
    [_progressBarImageView.layer addAnimation:ba forKey:@""];
}

- (void)setSuperView:(UIScrollView *)superView{
    _superView = superView;
}

- (void)setUpRefreshDidFinished{
    _isDidSendRequest = NO;
    _currentRefreshState = DidRefreshed;
    if ([self.subviews containsObject:_progressBarImageView]){
        [_progressBarImageView.layer removeAllAnimations];
        [_progressBarImageView removeFromSuperview];
    }
    if (![self.subviews containsObject:_backView]){
        [self addSubview:_backView];
    }
    self.hidden = YES;
}

- (void)resetUpRefreshState{
    _isSetOffset = NO;
    _currentRefreshState = NoneRefresh;
    _loadLab.text = k_LoadMoreTxt;
}

- (void)sendUpRefreshCommand{
    if(!_isDidSendRequest){
        _isDidSendRequest = YES;
        if(_delegate && [_delegate respondsToSelector:@selector(UpPullRequest)]){
            [_delegate UpPullRequest];
        }
    }
}

- (void)updatePostion{
    CGFloat superHeight = _superView.lx_height - _superView.contentInset.top - _superView.contentInset.bottom;
    self.lx_y = MAX(superHeight, _superView.contentSize.height);
}

- (void)setProgressValue:(CGFloat)progressValue{
    if(_currentRefreshState == DoingRefresh || _currentRefreshState == DidRefreshed){
        return;
    }
    _superOriginalContentInset = _superView.contentInset;
    CGFloat actualHeight = _superView.lx_height - _superOriginalContentInset.bottom - _superOriginalContentInset.top;
    CGFloat beyondHeight = _superView.contentSize.height - actualHeight;
    CGFloat showFooterOffset = beyondHeight - _superOriginalContentInset.top;
    if(beyondHeight < 0){
        showFooterOffset = -_superOriginalContentInset.top;
    }
    CGFloat actualOffset = progressValue - showFooterOffset;
    if (actualOffset > k_RefreshingHeight && _currentRefreshState == WillRefresh && _superView.isDragging) {
        _currentRefreshState = DoingRefresh;
    } else if (_superView.isDragging) {
        if (self.hidden) {
            self.hidden = NO;
        }
        _currentRefreshState = WillRefresh;
    }
    switch (_currentRefreshState) {
        case NoneRefresh:
        case WillRefresh:
            if (![self.subviews containsObject:_backView]) {
                [self addSubview:_backView];
            }
            [self updateProgressBarWithValue:actualOffset];
            break;
        case DoingRefresh:
            if ([self.subviews containsObject:_backView]) {
                [_backView removeFromSuperview];
                [self updateProgressBarWithValue:k_RefreshingHeight];
            }
            if (![self.subviews containsObject:_progressBarImageView]) {
                [self addSubview:_progressBarImageView];
                if (_progressBarImageView.image == nil) {
                    _progressBarImageView.image = [self getProgressBarImage];
                }
                [self setImageProgressBarAnimation];
                _loadLab.text = k_LoadingTxt;
            }
            break;
        default:
            break;
    }
    if (_superView.isDragging && _currentRefreshState == DoingRefresh) {
        [self sendUpRefreshCommand];
    }
    
}

@end

#pragma mark - 下拉刷新视图 -

@interface PullHeaderView : UIView
@property (nonatomic, assign)CGFloat                 defualtOffset;              //默认偏移
@property (nonatomic, assign)RefreshStatus        currentRefreshState;        //当前刷新状态
@property (nonatomic, assign)BOOL                    isCloseHeader;              //是否关闭头
@property (nonatomic, assign)BOOL                    isRequestEndNOInit;         //请求结束但没有初始化
@property (nonatomic, assign)UIEdgeInsets            superOriginalContentInset;  //super原始偏移值
- (void)setProgressValue:(CGFloat)progressValue;
- (void)setProgressBarEndDragPostion;
@end

@interface PullHeaderView () {
    UIView             *   _backView;                    //背景视图
    CAGradientLayer    *   _gradientProgressBar;         //渐变进度条层
    CAShapeLayer       *   _progressBar;                 //进度条层
    UIImageView        *   _progressBarImageView;        //图片进度条
    UILabel            *   _percentLab;                  //百分比
    UILabel            *   _refreshAlertLab;             //刷新提示
    UIScrollView       *   _superView;                   //父视图
    id                     _delegate;                    //刷新代理
    BOOL                   _isBreak;                     //水滴是否断开
    BOOL                   _isSetDefualtOffset;          //是否已经设置默认偏移
    BOOL                   _isDidRefresh;                //已经刷新过了
    BOOL                   _isDidSendRequest;            //是否已经发生请求
    CGFloat                _currentRadius;               //当前水滴半径
}
@end

@implementation PullHeaderView

- (instancetype)initWithFrame:(CGRect)frame delegate:(id<PullRefreshDelegate>)delegate{
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor whiteColor];
        _delegate = delegate;
        [self initData];
    }
    return self;
}

- (void)willMoveToSuperview:(UIView *)newSuperview {
    [super willMoveToSuperview:newSuperview];
    [_superView cancelledObsever];
    if (newSuperview) {
        [_superView addObserver];
    }
}

- (void)setSuperView:(UIScrollView *)superView{
    _superView = superView;
}

- (void)setDelegate:(id<PullRefreshDelegate>)delegate{
    _delegate = delegate;
}

- (UIView *)createView{
    UIView * view = [UIView new];
    view.lx_size = CGSizeMake(k_WaterDropSize, k_WaterDropSize);
    view.center = CGPointMake(self.lx_centerX, self.lx_height - k_WaterDropSize / 2.0);
    view.backgroundColor = [UIColor colorWithCGColor:k_WaterBackColor];
    view.layer.cornerRadius = k_WaterDropSize / 2.0;
    view.clipsToBounds = YES;
    return view;
}

- (void)initData {
    _defualtOffset = 0;
    _isSetDefualtOffset = NO;
    _currentRadius = k_WaterDropSize / 2.0;
    _backView = [self createView];
    [self addSubview:_backView];
    
    _gradientProgressBar = [CAGradientLayer layer];
    _gradientProgressBar.frame = _backView.bounds;
    _gradientProgressBar.backgroundColor = [UIColor clearColor].CGColor;
    _gradientProgressBar.colors = @[(id)K_StartColor, (id)K_EndColor];
    _gradientProgressBar.locations = @[@(0.0), @(1.0)];
    
    _progressBar = [CAShapeLayer layer];
    _progressBar.frame = _backView.bounds;
    _progressBar.backgroundColor = [UIColor clearColor].CGColor;
    _progressBar.fillColor = [UIColor clearColor].CGColor;
    _progressBar.strokeColor = [UIColor blueColor].CGColor;
    _progressBar.lineWidth = 5.0;
    _gradientProgressBar.mask = _progressBar;
    [_backView.layer addSublayer:_gradientProgressBar];
    
    _percentLab = [[UILabel alloc] initWithFrame:_backView.bounds];
    _percentLab.textAlignment = NSTextAlignmentCenter;
    _percentLab.textColor = k_HeaderPercentLabTxtColor;
    _percentLab.font = [UIFont systemFontOfSize:10.0];
    _percentLab.hidden = YES;
    [_backView addSubview:_percentLab];
    
    _progressBarImageView = [[UIImageView alloc] initWithFrame:_backView.frame];
    _progressBarImageView.lx_centerY = _progressBarImageView.lx_width / 2.0;
    
    _refreshAlertLab = [[UILabel alloc] initWithFrame:self.bounds];
    _refreshAlertLab.lx_height = k_WaterDropSize;
    _refreshAlertLab.center = _backView.center;
    _refreshAlertLab.textColor = k_HeaderLableTxtColor;
    _refreshAlertLab.font = [UIFont systemFontOfSize:k_FontSize];
    _refreshAlertLab.textAlignment = NSTextAlignmentCenter;
    _refreshAlertLab.text = k_RefreshFinishTxt;
}

- (void)updateProgressBarWithValue:(CGFloat)value {
    CGFloat  endAngle = value / k_PullHeight;
    if(endAngle > 1.0){
        endAngle = 1.0;
    }
    CGMutablePathRef  path = CGPathCreateMutable();
    CGPathAddArc(path, NULL, _progressBar.frame.size.width / 2.0, _progressBar.frame.size.height / 2.0, k_WaterDropSize / 2.0 - 2.5, M_PI / 2.0, endAngle * M_PI * 2.0 + M_PI / 2.0, NO);
    _progressBar.path = path;
    CGPathRelease(path);
    _percentLab.text = [NSString stringWithFormat:@"%.0f",endAngle * 100.0];
}

- (UIImage *)getProgressBarImage {
    UIGraphicsBeginImageContext(_gradientProgressBar.frame.size);
    CGContextRef  context  = UIGraphicsGetCurrentContext();
    [_gradientProgressBar renderInContext:context];
    return UIGraphicsGetImageFromCurrentImageContext();
}

- (void)setImageProgressBarAnimation {
    if(_progressBarImageView.image == nil){
        _progressBarImageView.image = [self getProgressBarImage];
    }
    _progressBarImageView.lx_centerY = _progressBarImageView.lx_height / 2.0;
    if(![self.subviews containsObject:_progressBarImageView]){
        [self addSubview:_progressBarImageView];
    }
    CABasicAnimation *ba = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    ba.fromValue = @(0);
    ba.toValue = @(M_PI * 2.0);
    ba.duration = 1.0;
    ba.cumulative = YES;
    ba.repeatCount = INFINITY;
    [_progressBarImageView.layer addAnimation:ba forKey:@""];
}

- (void)setProgressValue:(CGFloat)progressValue {
    if(_currentRefreshState != DoingRefresh && _currentRefreshState != DidRefreshed){
        _superOriginalContentInset = _superView.contentInset;
    }
    CGFloat actualOffset = progressValue + _superOriginalContentInset.top;
    CGFloat absActualOffset = -actualOffset;
    if (!_superView.isDragging) {
        if (_currentRefreshState == WillRefresh || _currentRefreshState == NoneRefresh) {
            if (absActualOffset > k_RefreshingHeight && absActualOffset <= k_PullHeight) {
                _backView.lx_centerY = self.lx_height - (absActualOffset - k_RefreshingHeight) - k_WaterDropSize / 2.0;
                _currentRadius = (1.0 - (absActualOffset - k_RefreshingHeight) / (k_PullHeight - k_Margin)) * k_WaterDropSize / 2.0;
            } else {
                _currentRadius = k_WaterDropSize / 2.0;
                _backView.lx_centerY = self.lx_height - k_WaterDropSize / 2.0;
            }
        }
        [self updateProgressBarWithValue:absActualOffset];
        [self setNeedsDisplay];
    } else {
        if (actualOffset < 0 && _currentRefreshState != DoingRefresh && _currentRefreshState != DidRefreshed) {
            if (_backView.hidden) {
                _backView.hidden = NO;
            }
            if (absActualOffset > k_RefreshingHeight) {
                if (absActualOffset <= k_PullHeight) {
                    _isBreak = NO;
                    _backView.lx_centerY = self.lx_height - (absActualOffset - k_RefreshingHeight) - k_WaterDropSize / 2.0;
                    _currentRadius = (1.0 - (absActualOffset - k_RefreshingHeight) / (k_PullHeight - k_Margin)) * k_WaterDropSize / 2.0;
                    _currentRefreshState = WillRefresh;
                    if(_currentRadius < k_BreakRadius){
                        _isBreak = YES;
                        _currentRefreshState = DoingRefresh;
                        _currentRadius = k_BreakRadius;
                    }
                } else {
                    _isBreak = YES;
                    _currentRadius = k_BreakRadius;
                    _currentRefreshState = DoingRefresh;
                    _backView.lx_centerY = k_RefreshingHeight / 2.0;
                }
                
            }
            [self updateProgressBarWithValue:absActualOffset];
            [self setNeedsDisplay];
            
            switch (_currentRefreshState) {
                case NoneRefresh:
                case WillRefresh:
                    if (![self.subviews containsObject:_backView]) {
                        [self addSubview:_backView];
                    }
                    break;
                case DoingRefresh: {
                    if([self.subviews containsObject:_backView]){
                        [_backView removeFromSuperview];
                        [self setImageProgressBarAnimation];
                    }
                }
                    break;
                case DidRefreshed:
                    break;
                default:
                    break;
            }
            if (_superView.isDragging && _currentRefreshState == DoingRefresh) {
                [self sendDownRefreshCommand];
            }
        }
    }
}

- (void)setDefualtOffset:(CGFloat)defualtOffset {
    if (!_isSetDefualtOffset) {
        _defualtOffset = defualtOffset;
        _isSetDefualtOffset = YES;
    }
}

- (void)setDownRefreshDidFinished {
    _currentRefreshState = DidRefreshed;
    _isDidRefresh = YES;
    if ([self.subviews containsObject:_progressBarImageView]) {
        _refreshAlertLab.lx_centerY = _progressBarImageView.lx_centerY;
        [_progressBarImageView removeFromSuperview];
        [self addSubview:_refreshAlertLab];
    }
}

- (void)resetDownRefreshState {
    [self updateProgressBarWithValue:0];
    [_progressBarImageView.layer removeAllAnimations];
    _progressBarImageView.lx_centerY = _progressBarImageView.lx_height / 2.0;
    _refreshAlertLab.lx_centerY = _refreshAlertLab.lx_height / 2.0;
    if ([self.subviews containsObject:_progressBarImageView]) {
        [_progressBarImageView removeFromSuperview];
    }
    if ([self.subviews containsObject:_refreshAlertLab]) {
        [_refreshAlertLab removeFromSuperview];
    }
    if (![self.subviews containsObject:_backView]) {
        [self addSubview:_backView];
    }
    _isRequestEndNOInit = NO;
    _isDidSendRequest = NO;
    _backView.lx_centerY = self.lx_height - k_WaterDropSize / 2.0;
    if (_currentRefreshState == WillRefresh) {
        _backView.hidden = NO;
    } else if (_currentRefreshState == DidRefreshed) {
        _backView.hidden = YES;
        _isCloseHeader = NO;
    }
    _isBreak = NO;
    _currentRefreshState = NoneRefresh;
    [self setNeedsDisplay];
}

- (void)setProgressBarEndDragPostion{
    _progressBarImageView.lx_centerY = self.lx_height - k_RefreshingHeight / 2.0;
}

- (void)sendDownRefreshCommand {
    if (![self.subviews containsObject:_progressBarImageView]) {
        [self addSubview:_progressBarImageView];
    }
    _progressBarImageView.lx_centerY = self.lx_height - k_RefreshingHeight / 2.0;
    if (!_isDidSendRequest) {
        _isDidSendRequest = YES;
        if (_delegate && [_delegate respondsToSelector:@selector(DownPullRequest)]) {
            [_delegate DownPullRequest];
        }
    }
}

- (void)drawRect:(CGRect)rect{
    if(_isBreak && (_currentRefreshState == DoingRefresh || _currentRefreshState == DidRefreshed)) {
        return;
    }
    CGPoint  a     = CGPointMake(_backView.lx_x + 0.5, _backView.lx_centerY),
             b     = CGPointMake(_backView.lx_maxX - 0.5, _backView.lx_centerY),
             c     = CGPointMake(_backView.lx_centerX + _currentRadius - 0.5, self.lx_height - _currentRadius),
             d     = CGPointMake(_backView.lx_centerX - _currentRadius + 0.5, self.lx_height - _currentRadius),
             ctr1  = CGPointMake(d.x, d.y - (self.lx_height - _currentRadius - _backView.lx_centerY) / 2.0),
             ctr2  = CGPointMake(c.x, c.y - (self.lx_height - _currentRadius - _backView.lx_centerY) / 2.0);
    
    UIBezierPath * bezierPath = [UIBezierPath bezierPath];
    bezierPath.lineJoinStyle = kCGLineJoinRound;
    bezierPath.lineCapStyle = kCGLineCapRound;
    [bezierPath moveToPoint:a];
    [bezierPath addQuadCurveToPoint:d controlPoint:ctr1];
    [bezierPath addLineToPoint:c];
    [bezierPath addQuadCurveToPoint:b controlPoint:ctr2];
    [bezierPath moveToPoint:a];
    [bezierPath closePath];
    
    CGContextRef  context = UIGraphicsGetCurrentContext();
    CGContextSetStrokeColorWithColor(context, k_WaterBackColor);
    CGContextSetFillColorWithColor(context, k_WaterBackColor);
    CGContextSetLineWidth(context, 1.0);
    if(_backView.hidden == NO){
        CGContextAddArc(context, d.x + _currentRadius - 0.5, d.y, _currentRadius - 0.5, 0, M_PI * 2.0, NO);
        CGContextDrawPath(context, kCGPathFillStroke);
        
        CGContextAddPath(context, bezierPath.CGPath);
        CGContextDrawPath(context, kCGPathFillStroke);
    }
    UIGraphicsEndImageContext();
}

@end

#pragma mark - 滚动视图分类 -

@implementation UIScrollView (PullRefresh)
const char HeaderMask = '8';
const char FooterMask = '9';

- (void)createHeaderViewWithDelegate:(id<PullRefreshDelegate>)delegate {
    PullHeaderView *headerView = [[PullHeaderView alloc]initWithFrame:CGRectMake(0, -k_PullHeight, CGRectGetWidth([UIScreen mainScreen].bounds), k_PullHeight) delegate:delegate];
    [headerView setSuperView:self];
    objc_setAssociatedObject(self, &HeaderMask, headerView, OBJC_ASSOCIATION_RETAIN);
    [self insertSubview:headerView atIndex:0];
}

- (void)createFooterViewWithDelegate:(id<PullRefreshDelegate>)delegate {
    PullFooterView   *  footerView = [[PullFooterView alloc] initWithFrame:CGRectMake(0, self.lx_height, CGRectGetWidth([UIScreen mainScreen].bounds), k_RefreshingHeight) delegate:delegate];
    [footerView setSuperView:self];
    objc_setAssociatedObject(self, &FooterMask, footerView, OBJC_ASSOCIATION_RETAIN);
    [self insertSubview:footerView atIndex:0];
}

- (void)hiddenFooterAndHeader:(BOOL)hide
{
    NSEnumerator *subviewsEnum = [self.subviews reverseObjectEnumerator];
    for (UIView *subview in subviewsEnum) {
        if ([subview isKindOfClass:[PullFooterView class]] || [subview isKindOfClass:[PullHeaderView class]]) {
            subview.hidden = hide;
        }
    }
}

- (void)setRefreshStyle:(PullRefreshStyle)refreshStyle  delegate:(id<PullRefreshDelegate>)delegate {
    [self addObserver];
    switch (refreshStyle) {
        case AllStyle:
            [self createFooterViewWithDelegate:delegate];
            [self createHeaderViewWithDelegate:delegate];
            break;
        case FooterStyle:
            [self createFooterViewWithDelegate:delegate];
            break;
        case HeaderStyle:
            [self createHeaderViewWithDelegate:delegate];
            break;
        case hiddenStyle:
            [self hiddenFooterAndHeader:YES];
            break;
        case showStyle:
            [self hiddenFooterAndHeader:NO];
            break;
        default:
            break;
    }
}

- (PullHeaderView *)getHeaderView {
    return objc_getAssociatedObject(self, &HeaderMask);
}

- (PullFooterView *)getFooterView {
    return objc_getAssociatedObject(self, &FooterMask);
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([keyPath isEqualToString:k_ContentOffset]) {
        [self scrollViewDidScroll:[change[NSKeyValueChangeNewKey] CGPointValue]];
    } else if ([keyPath isEqualToString:k_ContentSize]) {
        PullFooterView  * footerView = [self getFooterView];
        if(footerView){
            [footerView updatePostion];
        }
    }
}

- (void)DidCompletedWithRefreshIsDownPull:(BOOL)isDown {
    __weak  typeof(self)  sf = self;
    if (isDown) {
        PullHeaderView  *headerView = [self getHeaderView];
        if (headerView) {
            [headerView setDownRefreshDidFinished];
            double delayInSeconds = .3;
            dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
            dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
                [UIView animateWithDuration:k_OffsetAnimationTime delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
                    sf.contentInset = UIEdgeInsetsMake(headerView.superOriginalContentInset.top, 0, headerView.superOriginalContentInset.bottom, 0);
                } completion:^(BOOL finished) {
                    if (!self.isDragging) {
                        [headerView resetDownRefreshState];
                    } else {
                        headerView.isRequestEndNOInit = YES;
                    }
                }];
            });
        }
    } else {
        PullFooterView *footerView = [self getFooterView];
        if (footerView) {
            [footerView setUpRefreshDidFinished];
            [UIView animateWithDuration:k_OffsetAnimationTime delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
                sf.contentInset = UIEdgeInsetsMake(footerView.superOriginalContentInset.top, 0, footerView.superOriginalContentInset.bottom, 0);
            } completion:^(BOOL finished) {
                footerView.isSetOffset = NO;
                if (!self.isDragging) {
                    [footerView resetUpRefreshState];
                }
            }];
        }
    }
}

- (void)scrollViewDidScroll:(CGPoint )contentOffset {
    CGFloat  defaultOffset = 0.0;
    PullHeaderView *headerView = [self getHeaderView];
    PullFooterView *footerView = [self getFooterView];
    if (headerView) {
        defaultOffset = headerView.superOriginalContentInset.top;
    } else if (footerView) {
        defaultOffset = footerView.superOriginalContentInset.top;
    }
    __weak  typeof(self)  sf = self;
    if (contentOffset.y < -defaultOffset && headerView) {
        if (!self.isDragging) {
            [self scrollViewDidEndDraggingWithwillDecelerate:YES isUp:NO];
        } else {
            if (-contentOffset.y < self.contentInset.top) {
                if (!headerView.isCloseHeader && headerView.currentRefreshState == DoingRefresh) {
                    headerView.isCloseHeader = YES;
                    [UIView animateWithDuration:k_OffsetAnimationTime delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
                        sf.contentInset = UIEdgeInsetsMake(headerView.superOriginalContentInset.top, 0, headerView.superOriginalContentInset.bottom, 0);
                    } completion:nil];
                    
                }
            } else if (-contentOffset.y >= self.contentInset.top + k_RefreshingHeight) {
                if (headerView.isCloseHeader && headerView.currentRefreshState == DoingRefresh) {
                    headerView.isCloseHeader = NO;
                    [UIView animateWithDuration:k_OffsetAnimationTime delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
                        sf.contentInset = UIEdgeInsetsMake(headerView.superOriginalContentInset.top + k_RefreshingHeight, 0, headerView.superOriginalContentInset.bottom, 0);
                    } completion:nil];
                }
            }
        }
        if (footerView && footerView.currentRefreshState == DidRefreshed) {
            [footerView resetUpRefreshState];
        }
        [headerView setProgressValue:contentOffset.y];
    } else {
        if (!self.isDragging) {
            [self scrollViewDidEndDraggingWithwillDecelerate:YES isUp:YES];
        }
        
        if (headerView && headerView.currentRefreshState == DidRefreshed) {
            [headerView resetDownRefreshState];
        }
        if (footerView) {
            [footerView setProgressValue:contentOffset.y];
        }
    }
}

- (void)scrollViewDidEndDraggingWithwillDecelerate:(BOOL)decelerate isUp:(BOOL)isUp {
    __weak  typeof(self)  sf = self;
    if (isUp) {
        PullFooterView *footerView = [self getFooterView];
        if (footerView) {
            if (footerView.currentRefreshState == DoingRefresh && !footerView.isSetOffset) {
                footerView.isSetOffset = YES;
                [UIView animateWithDuration:k_OffsetAnimationTime delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
                    sf.contentInset = UIEdgeInsetsMake(footerView.superOriginalContentInset.top, 0, k_RefreshingHeight + footerView.superOriginalContentInset.bottom, 0);
                } completion:nil];
            } else if (!footerView.isSetOffset) {
                [footerView resetUpRefreshState];
            }
        }
    } else {
        PullHeaderView *headerView = [self getHeaderView];
        if (headerView) {
            if (headerView.currentRefreshState == DoingRefresh) {
                if (!headerView.isCloseHeader) {
                    sf.contentInset = UIEdgeInsetsMake(k_RefreshingHeight + headerView.superOriginalContentInset.top, 0, headerView.superOriginalContentInset.bottom, 0);
                }
                [headerView setProgressBarEndDragPostion];
//            }[headerView resetDownRefreshState];
            } else if (headerView.currentRefreshState != DidRefreshed || headerView.isRequestEndNOInit) {
                [headerView resetDownRefreshState];
            }
        }
    }
}

- (void)addObserver{
    [self addObserver:self forKeyPath:k_ContentOffset options:NSKeyValueObservingOptionNew context:nil];
    [self addObserver:self forKeyPath:k_ContentSize options:NSKeyValueObservingOptionNew context:nil];
}

- (void)cancelledObsever{
    [self removeObserver:self forKeyPath:k_ContentSize context:nil];
    [self removeObserver:self forKeyPath:k_ContentOffset context:nil];
}

@end
